/**
 * 
 */
package cn.egame.identify.app.extraction.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Logger;

import cn.egame.common.efs.IFileSystem;
import cn.egame.common.efs.SFileSystemClient;
import cn.egame.common.exception.ExceptionCommonBase;
import cn.egame.common.util.Utils;
import cn.egame.identify.app.extraction.dao.IdentifyAppDao;
import cn.egame.identify.app.extraction.pojo.IdentifyApp;
import cn.egame.identify.app.extraction.util.DateUtil;

/**
 * Description TODO
 * 
 * @ClassName IdentifyAppService
 * 
 * @Copyright 炫彩互动
 * 
 * @Project egame.mobile.extraction
 * 
 * @Author zhangjb
 * 
 * @Create Date 2014年3月7日
 * 
 * @Modified by none
 * 
 * @Modified Date
 */

public class IdentifyAppService {

    public static IdentifyAppService instance = null;
    private static byte[] lock = new byte[0];
    private Logger log = Logger.getLogger(IdentifyAppService.class.getSimpleName());
    private IdentifyAppDao identifyAppDao = null;
    private List<String> packageNames = null;
    private Properties properties = null;
    private static String FILE_NAME = "maxversion_";
    private static String FILE_TYPE = ".txt";

    static{
        Utils.initLog4j();
    }
    
    public static IdentifyAppService getInstance() throws ExceptionCommonBase {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new IdentifyAppService();
                }
            }
        }
        return instance;
    }

    private IdentifyAppService() throws ExceptionCommonBase {
        identifyAppDao = new IdentifyAppDao();
        try {
            properties = Utils.getProperties("common.properties");
        } catch (FileNotFoundException e) {
            log.error("read file error" + e);
        }
    }

    /**
     * @Description: 判断所给应用是否在游戏文件表中
     * @param app　传入的应用
     * @return 如果存在，返回true，否则false
     */
    public boolean isAppExistInGameFile(IdentifyApp app) {
        boolean flag = false;
        if (packageNames != null) {
            if (packageNames.contains(app.getPacketName())) {
                flag = true;
            }
        }
        return flag;
    }
    
    /**@Description: 跟新或者新增一条未识别应用记录
     * @param app 传入的应用
     * @return 更新的数量
     */
    public int upsertIdentifyApp(IdentifyApp app) throws ExceptionCommonBase{
        return identifyAppDao.setIdentifyApp(app);
    }
    
    /**@Description: 将String字符串转换为IdentifyApp对象
     * @param app 传入的字符串
     * @return 转换后的IdentifyApp对象
     */
    public IdentifyApp compareStringToApp(String app) {
        String[] tempArr = app.split("\\|");
        IdentifyApp identifyApp = new IdentifyApp();
        if (tempArr != null && tempArr.length >= 4 ) {
            identifyApp.setPacketName(tempArr[0].trim());
            identifyApp.setName(tempArr[1].trim());
            identifyApp.setVersionCode(Integer.parseInt(tempArr[2].trim()));
            identifyApp.setInstall(Integer.parseInt(tempArr[3].trim()));
            identifyApp.setStatus(1);
        }
        return identifyApp;
    }
    
    /**@Description: 从文件导入所有应用的信息
     * @param filePath 文件路径
     * @throws ExceptionCommonBase 
     */
    public void importAppData(String filePath) throws ExceptionCommonBase {
        File file = new File(filePath);
        BufferedReader read = null;
        int updatedRecord = 0;
        packageNames = identifyAppDao.getPackageName();
        log.info("开始导入未识别应用数据...");
        try {
            read = new BufferedReader(new FileReader(file));
            String appString = null;
            while ((appString = read.readLine()) != null) {
                IdentifyApp appObject = this.compareStringToApp(appString);
                //如果应用不存在于游戏文件表中，则去未识别表跟新记录，否则跳过
                boolean isExist = this.isAppExistInGameFile(appObject);
                if (!isExist) {
                    this.upsertIdentifyApp(appObject);
//                    System.out.println(appObject.getName() + "  " + appObject.getPacketName());
                    updatedRecord ++;
                }
            }
            log.info("跟新记录数为：" + updatedRecord);
            log.info("导入未识别应用成功...");
            read.close();
        } catch (FileNotFoundException e) {
            log.error("文件没找到:" + filePath);
        } catch (ExceptionCommonBase e) {
            log.error(e);
        } catch (IOException e) {
            log.error(e);
        }  finally {
            if (read != null) {
                try {
                    read.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
    }
    
    /**@Description: 从远端服务下载文件
     * @param filePath 文件路径
     * @throws ExceptionCommonBase
     * @return 生成的文件完整路徑
     */
    public String downloadFile(int runCount) throws ExceptionCommonBase{
        FileOutputStream fos = null;
        String localFilePath = null;
        log.info("开始文件抓取...");
        try {
            IFileSystem fileSystem = SFileSystemClient.getInstance("egame");
            String localFileRoot = properties.getProperty("local_file_root");
            new File(localFileRoot).mkdirs();
            localFilePath = localFileRoot + FILE_NAME + DateUtil.formatCurrentDate() + FILE_TYPE;
            log.info("本地文件路劲：" + localFilePath);
            
            String readRootPath = properties.getProperty("upload_write_address");
            String readPath = readRootPath + FILE_NAME + DateUtil.formatCurrentDate() + FILE_TYPE;
            log.info("读取文件路径：" + readPath);
            
            File file = new File(localFilePath);
            fos = new FileOutputStream(file);
            boolean isSuccess = fileSystem.getOutputStream(fos, readPath);
            if (!isSuccess) {
                throw new Exception("抓取文件失败");
            }
            log.info("抓取文件结束...");
        } catch (Exception e) {
            log.error(e);
            log.error("抓取文件出错：重新抓取：" + runCount);
            if(runCount < 5){
                downloadFile(++runCount);
            }
            
        } finally{
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e1) {
                    log.error(e1);
                }
            }
        }
        return localFilePath;
    }
    
    public static void main(String[] args) {
        try {
            long start = System.currentTimeMillis();
            IdentifyAppService ias = new IdentifyAppService();
            String filePath = ias.downloadFile(1);
            ias.importAppData(filePath);
            long end = System.currentTimeMillis();
            long time = end - start;
        } catch (ExceptionCommonBase e) {
            e.printStackTrace();
        }
    }
}
